// "a (b c 1 nil null) true [] 'str"
// {
// 	type:"jisp",
// 	value:[
// 		{type:"jisp-symbol",value:"a"},
// 		{
// 			type:"jisp",
// 			value:[
// 					{type:"jisp-symbol",value:"b"},
// 					{type:"jisp-symbol",value:"c"},
// 					1,
// 					null,
// 					null
// 			]
// 		},
// 		true,
// 		[],
// 		"str"
// 	]
// }

;(function(exports,r){
    var head=r.head;
    var tail=r.tail;
    var pipe=r.pipe;
    var map=r.map;
    var last=r.last;
    var reduce=r.reduce;
    //jisp基础数据类型
    var makeToken=r.cond([
	[isStringToken,makeString],
	[isNumberToken,makeNumber],
	[isBooleanToken,makeBoolean],
	[isNilToken,r.always(null)],
	[isArrayToken,makeArray],
	[isJispToken,makeJisp],
	[r.T,makeSymbol]
    ]);
    function not(a){
	return !a;
    }
    //去头去尾
    var tailInit=r.pipe(tail,r.init);
    function isNumberToken(a){
	return not(isNaN(Number(a)));
    }
    function makeNumber(str){
	return Number(str);
    }
    function isStringToken(str){
	return head(str)=="'";
    }
    function makeString(str){
	return tail(str);
    }
    function isBooleanToken(str){
	return str=="true"||str=="false";
    }
    function makeBoolean(str){
	if(str=="true")return true;
	return false;
    }
    function isNilToken(str){
	return str=="nil"||str=="null";
    }
    function isArrayToken(str){
	return head(str)=="["&&last(str)=="]";
    }
    function makeArray(str){
	return parseToken(tailInit(str));
    }
    function isJispToken(str){
	return head(str)=="("&&last(str)==")";
    }
    function isSymbol(obj){
	return obj&&obj.type=="jisp-symbol";
    }
    function makeSymbol(a){
	return {
	    type:"jisp-symbol",
	    value:a
	}
    }
    
    function makeJisp(str){
	return {
	    type:"jisp",
	    value:parseToken(tailInit(str))
	}
    }

    function isTokenEnd(endpro,ttoken){
	return endpro[0].apply(null,r.concat(tail(endpro),[ttoken]));
    }
    function isJispEnd(num,ttoken){
	return num==1&&ttoken==")";
    }
    function isArrayEnd(num,ttoken){
	return num==1&&ttoken=="]";	
    }
    function _parseToken(str,token,endpro){
	//jisp结束
	if(r.isEmpty(str)){
	    if(head(endpro)==isArrayEnd) throw "jisp-> array缺少右括号->"+token;
	    if(head(endpro)==isJispEnd) throw "jisp-> jisp缺少右括号->"+token;
	    if(r.isEmpty(token)) return [];
	    return [makeToken(token)];
	}
	var ttoken=head(str);
	if(isTokenEnd(endpro,ttoken)){
	    if(ttoken==")")token+=")";
	    if(ttoken=="]")token+="]";
	    return r.concat([makeToken(token)],_parseToken(tail(str),"",[r.F]));
	}
	if(r.equals(endpro,[r.F])){
	    if(ttoken=="("){
		return _parseToken(tail(str),token+ttoken,[isJispEnd,1]);
	    }
	    if(ttoken=="["){
		return _parseToken(tail(str),token+ttoken,[isArrayEnd,1]);
	    }
	    if(ttoken==" ") return _parseToken(tail(str),"",[r.F]);;
	    return _parseToken(tail(str),token+ttoken,[r.equals," "]);
	}
	if(head(endpro)==isArrayEnd){
	    if(ttoken=="["){
		endpro[1]++;
	    }
	    if(ttoken=="]"){
		endpro[1]--;
	    }
	}
	if(head(endpro)==isJispEnd){
	    if(ttoken=="("){
		endpro[1]++;
	    }			
	    if(ttoken==")"){
		endpro[1]--;
	    }
	}
	return _parseToken(tail(str),token+ttoken,endpro);
    }

    function parseToken(str){
	return _parseToken(str,"",[r.F]);
    }
    function getJispFn(jisp){
	var symbol = head(jisp.value);
	return symbol;
	// throw "jisp-> 函数名字必须是符号（非数字,字符串,true,flase,nil,null)";
    }
    function getJispFnName(jisp){
	return getSymbol(getJispFn(jisp));
    }
    function getJispArgs(jisp){
	return tail(jisp.value);
    }
    function isJisp(obj){
	return obj&&obj.type=="jisp";
    }
    function pushJispArg(jisp,arg){
	function fn(a){
	    if(isSymbol(a)) return getSymbol(a)=="__";
	    return false;
	}
	function fn1(a){
	    if(fn(a)) return arg;
	    return a;
	}
	if(isJisp(jisp)){
	    if(r.any(fn,jisp.value)) return r.assoc("value",r.map(fn1,jisp.value),jisp);
	    return r.assoc("value",r.concat(jisp.value,[arg]),jisp);
	}
	if(isSymbol(jisp)){
	    return pushJispArg(makeJisp("("+getSymbol(jisp)+")"),arg);
	}
	throw "必须是jisp表达式 才使用pushJispArg";
    }
    function getSymbol(symbol){
	return symbol.value;
    }
    //宏
    var jispMacro={
    };
    function isJispMacro(symbol){
	return jispMacro[symbol]!=null;
    }
    function getJispMacro(symbol){
	return jispMacro[symbol];
    }
    function runMacro(symbol,args){
	return getJispMacro(symbol).apply(null,args);
    }
    function toArray(a){
	return [].slice.call(a, 0);
    }
    function parseMacro(jisp){
	if(isJisp(jisp)){
	    if(isJispMacro(getJispFnName(jisp))){
		return runMacro(getJispFnName(jisp),getJispArgs(jisp));
	    }
	    return jisp;
	}
	return jisp;
    }
    function getSymbolValue (symbol,context) {
	return r.path(getSymbol(symbol).split("."),context);
    }
    function run(jispobj,context){
	//如果是符号
	if(isSymbol(jispobj))return getSymbolValue(jispobj,context);
	//如果是数组
	if(r.is(Array,jispobj)) return r.map(r.converge(run,[r.identity,r.always(context)]),jispobj);
	//如果是jisp
	if(isJisp(jispobj)) {
	    var fn=run(getJispFn(jispobj),context);
	    if(pipe(r.is(Function),r.not)(fn))throw getJispFnName(jispobj)+"->不是一个函数";
	    return fn.apply(null,run(getJispArgs(jispobj),context));
	}
	//如果是基本数据
	return jispobj;
    }
    function evail(jispstr,context){
	console.time("evail");
	var resrult=run(parser(jispstr),r.merge(r,context));
	console.timeEnd("evail");
	return resrult;
    }
    function parser(str){
	var t= parseToken(str);
	var r=parseMacro(last(t));
	return r;
    }
    //宏扩展
    function defmacro(name,fn){
	if(jispMacro[name]!=null)throw "宏"+name+"已经存在";
	jispMacro[name]=fn;
    }
    //宏处理
    function macroJisp(){
	return {
	    type:"jisp",
	    value:toArray(arguments)
	}
    }
    defmacro("=",function(a,b){
	return macroJisp(makeSymbol("equals"),a,b);
    });
    defmacro(">",function(a,b){
	return macroJisp(makeSymbol("gt"),a,b);
    });
    defmacro(">=",function(a,b){
	return macroJisp(makeSymbol("gte"),a,b);
    });
    defmacro("<",function(a,b){
	return macroJisp(makeSymbol("lt"),a,b);
    });
    defmacro("<=",function(a,b){
	return macroJisp(makeSymbol("lte"),a,b);
    });
    defmacro("|>",function(){
	var arr=toArray(arguments);
	var stx=r.filter(function(a){
	    if(isSymbol(a)) return getSymbol(a) != "|>";
	    return true;
	},r.reverse(arr));
	function fn(x,xs){
  	    if(r.isEmpty(xs)) return parseMacro(x);
	    return pushJispArg(parseMacro(x),fn(head(xs),tail(xs)));
	}
	return fn(head(stx),tail(stx));
    });
    exports.jisp={
	run:run,
	parser:parser,
	defmacro:defmacro,
	evail:evail,
	parseMacro:parseMacro,
	macroJisp:macroJisp,
	pushJispArg:pushJispArg
    }
}(this,R));


